package com.ruoyi.cms.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.green20220302.Client;
import com.aliyun.green20220302.models.*;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.ruoyi.api.feign.ContentModerationService;
import com.ruoyi.common.enums.cms.FileRiskLevelEnum;
import com.ruoyi.common.exception.modules.CmsException;
import com.ruoyi.common.utils.oss.OssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 内容审核服务实现类
 */
@Service
@Slf4j
public class ContentModerationServiceImpl implements ContentModerationService {


    /**
     * 创建深圳请求客户端
     */
    public Client createSZClient() throws Exception {
        return createClient("cn-shenzhen");
    }

    /**
     * 创建上海请求客户端
     */
    public Client createSHClient() throws Exception {
        return createClient("cn-shanghai");
    }

    /**
     * 创建请求客户端
     */
    private Client createClient(String regionId) throws Exception {
        Config config = new Config();

        String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");

        config.setAccessKeyId(accessKeyId);
        config.setAccessKeySecret(accessKeySecret);
        //接入区域和地址请根据实际情况修改
        config.setRegionId(regionId);
        config.setEndpoint("green-cip." + regionId + ".aliyuncs.com");
        //读取时超时时间，单位毫秒（ms）。
        config.setReadTimeout(6000);
        //连接时超时时间，单位毫秒（ms）。
        config.setConnectTimeout(3000);

        return new Client(config);
    }

    /**
     * 文本内容审核
     */
    public boolean textModeration(String text, Client client) {
        if (StrUtil.isBlank(text)){
            return true;
        }
        try {
            JSONObject serviceParameters = new JSONObject();
            serviceParameters.put("content", text);

            TextModerationPlusRequest textModerationPlusRequest = new TextModerationPlusRequest();
            // 检测类型
            textModerationPlusRequest.setService("nickname_detection_pro");
            textModerationPlusRequest.setServiceParameters(serviceParameters.toJSONString());

            TextModerationPlusResponse response = client.textModerationPlus(textModerationPlusRequest);
            if (response.getStatusCode() == 200) {
                TextModerationPlusResponseBody result = response.getBody();
                log.info("文本内容审核:'" + text + "'， 返回" + JSON.toJSONString(result));
                Integer code = result.getCode();
                if (200 == code) {
                    TextModerationPlusResponseBody.TextModerationPlusResponseBodyData data = result.getData();
                    String riskLevel = data.getRiskLevel();
                    return !FileRiskLevelEnum.HIGH.getLevel().equals(riskLevel)
                            && !FileRiskLevelEnum.MEDIUM.getLevel().equals(riskLevel);
                } else {
                    log.error("text moderation not success. code:" + code);
                }
            } else {
                log.error("response not success. status:" + response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("text moderation error", e);
        }
        throw new CmsException("text moderation error");
    }

    /**
     * 提交图片内容检测（同步）
     */
    public boolean imageUrlModeration(String imageUrl, Client client) {
        if(StrUtil.isBlank(imageUrl)){
            return true;
        }
        return imageModeration(imageUrl.substring(OssUtil.domainLength), client);
    }

    /**
     * 提交图片内容检测（同步）
     */
    public boolean imageModeration(String ossObjectName, Client client) {
        try {
            // 创建RuntimeObject实例并设置运行参数
            RuntimeOptions runtime = new RuntimeOptions();
            // 检测参数构造。
            Map<String, String> serviceParameters = new HashMap<>();
            //待检测数据唯一标识
            serviceParameters.put("dataId", UUID.randomUUID().toString());
            // 待检测文件所在bucket的区域。 示例：cn-shanghai
            serviceParameters.put("ossRegionId", OssUtil.region);
            // 待检测文件所在bucket名称。示例：bucket001
            serviceParameters.put("ossBucketName", OssUtil.bucketName);
            // 待检测文件。 示例：image/001.jpg
            serviceParameters.put("ossObjectName", ossObjectName);

            ImageModerationRequest request = new ImageModerationRequest();
            // 图片检测service：内容安全控制台图片增强版规则配置的serviceCode，示例：baselineCheck
            // 支持service请参考：https://help.aliyun.com/document_detail/467826.html?0#p-23b-o19-gff
            request.setService("baselineCheck");
            request.setServiceParameters(JSON.toJSONString(serviceParameters));

            ImageModerationResponse response = client.imageModerationWithOptions(request, runtime);

            // 打印检测结果。
            if (response.getStatusCode() == 200) {
                ImageModerationResponseBody body = response.getBody();
                log.info("图片内容审核返回：" + JSON.toJSONString(body));

                if (body.getCode() == 200) {
                    ImageModerationResponseBody.ImageModerationResponseBodyData data = body.getData();
                    log.info("dataId=" + data.getDataId());
                    String riskLevel = data.getRiskLevel();
                    return !FileRiskLevelEnum.HIGH.getLevel().equals(riskLevel)
                            && !FileRiskLevelEnum.MEDIUM.getLevel().equals(riskLevel);
                } else {
                    log.error("image moderation not success. code:" + body.getCode());
                }
            } else {
                log.error("response not success. status:" + response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("image moderation error", e);
        }
        throw new CmsException("image moderation error");
    }

    /**
     * 提交图片内容检测（异步）
     */
    public String imageUrlAsyncModeration(String imageUrl, Client client) throws Exception {
        return imageAsyncModeration(imageUrl.substring(OssUtil.domainLength), client);
    }

    /**
     * 提交图片内容检测（异步）
     */
    public String imageAsyncModeration(String ossObjectName, Client client) throws Exception {
        // 创建RuntimeObject实例并设置运行参数
        RuntimeOptions runtime = new RuntimeOptions();
        // 检测参数构造。
        Map<String, String> serviceParameters = new HashMap<>();
        //待检测数据唯一标识
        serviceParameters.put("dataId", UUID.randomUUID().toString());
        // 待检测文件所在bucket的区域。 示例：cn-shanghai
        serviceParameters.put("ossRegionId", OssUtil.region);
        // 待检测文件所在bucket名称。示例：bucket001
        serviceParameters.put("ossBucketName", OssUtil.bucketName);
        // 待检测文件。 示例：image/001.jpg
        serviceParameters.put("ossObjectName", ossObjectName);

        ImageAsyncModerationRequest imageAsyncModerationRequest = new ImageAsyncModerationRequest();
        // 图片检测service：内容安全控制台图片增强版规则配置的serviceCode，示例：baselineCheck
        // 支持service请参考：https://help.aliyun.com/document_detail/467826.html?0#p-23b-o19-gff
        imageAsyncModerationRequest.setService("baselineCheck");
        imageAsyncModerationRequest.setServiceParameters(JSON.toJSONString(serviceParameters));
        ImageAsyncModerationResponse response = client.imageAsyncModerationWithOptions(imageAsyncModerationRequest, runtime);

        if (response != null) {
            if (response.getStatusCode() == 200) {
                ImageAsyncModerationResponseBody body = response.getBody();
                log.info(JSON.toJSONString(body));
                if (body.getCode() == 200) {
                    ImageAsyncModerationResponseBody.ImageAsyncModerationResponseBodyData data = body.getData();
                    return data.getReqId();
                } else {
                    log.error("image asyncmoderation not success. code:" + body.getCode());
                }
            } else {
                log.error("asyncmoderation response not success. status:" + response.getStatusCode());
            }
        }
        throw new CmsException("image asyncmoderation error");
    }

    /**
     * 获取图片内容检测结果
     */
    public DescribeImageModerationResultResponseBody.DescribeImageModerationResultResponseBodyData getImageResult(String reqId, Client client) throws Exception {
        DescribeImageModerationResultRequest describeImageModerationResultRequest = new DescribeImageModerationResultRequest();
        // 提交任务时返回的reqId
        describeImageModerationResultRequest.setReqId(reqId);

        DescribeImageModerationResultResponse response = client.describeImageModerationResult(describeImageModerationResultRequest);
        if (response.getStatusCode() == 200) {
            DescribeImageModerationResultResponseBody result = response.getBody();
            log.info(JSON.toJSONString(result));
            if (200 == result.getCode()) {
                return result.getData();
            } else if (280 == result.getCode() || 288 == result.getCode()) {
                log.info("image async moderation..." + result.getCode());
                return new DescribeImageModerationResultResponseBody.DescribeImageModerationResultResponseBodyData();
            } else {
                log.error("image async moderation result not success. code:" + result.getCode());
            }
        } else {
            log.error("response not success. status:" + response.getStatusCode());
        }
        throw new CmsException("image async moderation error");
    }

    /**
     * 提交视频内容检测任务
     */
    public String videoUrlModeration(String videoUrl, Client client) throws Exception {
        return videoModeration(videoUrl.substring(OssUtil.domainLength), client);
    }

    /**
     * 提交视频内容检测任务
     */
    public String videoModeration(String ossObjectName, Client client) throws Exception {
        JSONObject serviceParameters = new JSONObject();
        serviceParameters.put("ossBucketName", OssUtil.bucketName);
        serviceParameters.put("ossObjectName", ossObjectName);
        serviceParameters.put("ossRegionId", OssUtil.region);

        VideoModerationRequest videoModerationRequest = new VideoModerationRequest();
        // 检测类型：videoDetection
        videoModerationRequest.setService("videoDetection");
        videoModerationRequest.setServiceParameters(serviceParameters.toJSONString());
        VideoModerationResponse response = client.videoModeration(videoModerationRequest);
        if (response.getStatusCode() == 200) {
            VideoModerationResponseBody result = response.getBody();
            log.info(JSON.toJSONString(result));

            Integer code = result.getCode();
            if (200 == code) {
                VideoModerationResponseBody.VideoModerationResponseBodyData data = result.getData();
                return data.getTaskId();
            } else {
                log.error("video moderation not success. code:" + code);
            }
        } else {
            log.error("response not success. status:" + response.getStatusCode());
        }
        throw new CmsException("video moderation error");
    }

    /**
     * 获取视频检测任务结果
     */
    public VideoModerationResultResponseBody.VideoModerationResultResponseBodyData getVideoResult(String taskId, Client client) throws Exception {
        JSONObject serviceParameters = new JSONObject();
        // 提交任务时返回的taskId。
        serviceParameters.put("taskId", taskId);

        VideoModerationResultRequest videoModerationResultRequest = new VideoModerationResultRequest();
        // 检测类型：videoDetection
        videoModerationResultRequest.setService("videoDetection");
        videoModerationResultRequest.setServiceParameters(serviceParameters.toJSONString());
        VideoModerationResultResponse response = client.videoModerationResult(videoModerationResultRequest);
        if (response.getStatusCode() == 200) {
            VideoModerationResultResponseBody result = response.getBody();
            log.info(JSON.toJSONString(result));
            if (200 == result.getCode()) {
                return result.getData();
            } else if (280 == result.getCode() || 288 == result.getCode()) {
                log.info("video moderation..." + result.getCode());
                return new VideoModerationResultResponseBody.VideoModerationResultResponseBodyData();
            } else {
                log.error("video moderation result not success. code:" + result.getCode());
            }
        } else {
            log.error("response not success. status:" + response.getStatusCode());
        }
        throw new CmsException("video moderation result error");
    }


}
